﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AirTickets;
using System.ComponentModel;
using System.Linq.Expressions;
using System.IO;
using System.Xml.Serialization;
using System.Xml;

namespace AirTickets
{
    public enum EstadoBillete
    {
        Disponible, Reservado, Comprado
    }

    public class Billete : INotifyPropertyChanged, IEquatable<Billete>
    {
        Asiento _asiento;
        Vuelo _vuelo;
        EstadoBillete _estado;
        string _codigo;

        #region Constructors

        public Billete()
        {
            _codigo = Guid.NewGuid().ToString();
        }

        public Billete(bool showUI)
            : this()
        {
            if (showUI)
            {
                BilleteForm form = new BilleteForm(this);
                if (form.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {

                }
            }

        }

        public Billete(Vuelo vuelo)
            : this()
        {
            _vuelo = vuelo;
        }

        public Billete(Vuelo vuelo, bool showUI)
            : this(vuelo)
        {

            BilleteForm form = new BilleteForm(this);
            if (showUI)
                if (form.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {

                }
        }

        private Billete(
            string salida,
            string llegada,
            DateTime fecha_salida)
            : this()
        {
            ListaDeAeropuertos aeropuertos = new ListaDeAeropuertos();

            Aeropuerto aeropuertoSalida = aeropuertos.Single(x => string.Compare(x.Codigo, salida, true) == 0 || string.Compare(x.Ciudad, salida, true) == 0);
            if (aeropuertoSalida == null)
                throw new Exception("El aeropuerto de salida no se encuentra en la lista");

            Aeropuerto aeropuertoLlegada = aeropuertos.Single(x => string.Compare(x.Codigo, llegada, true) == 0 || string.Compare(x.Ciudad, llegada, true) == 0);
            if (aeropuertoLlegada == null)
                throw new Exception("El aeropuerto de llegada no se encuentra en la lista");

            ListaDeVuelos vuelos = new ListaDeVuelos();

            Vuelo v = vuelos.First(x => x.SirvePara(salida, llegada, fecha_salida));
            if (v == null)
                throw new Exception("No se encontraron vuelos para ese origen, destino y fecha");
        }

        private Billete(Vuelo vuelo, Asiento asiento)
            : this()
        {
            _asiento = asiento;
            _vuelo = vuelo;
            _estado = EstadoBillete.Disponible;
        }

        #endregion

        #region Prorperies

        [XmlIgnore]
        public string Codigo
        {
            get
            {
                return _codigo;
            }
        }

        public string Pasajero
        {
            get;
            set;
        }

        [XmlIgnore]
        public Vuelo Vuelo
        {
            get { return _vuelo; }
            internal set { _vuelo = value; OnPropertyChanged(() => this.Vuelo); }
        }

        [XmlIgnore]
        public Asiento Asiento
        {
            get { return _asiento; }
            internal set { _asiento = value; OnPropertyChanged(() => this.Asiento); }
        }

        [XmlIgnore]
        public EstadoBillete Estado
        {
            get { return _estado; }
            private set { _estado = value; OnPropertyChanged(() => this.Estado); }
        }

        [XmlIgnore]
        public string DescriptorAsiento
        {
            get
            {
                return _asiento.Descriptor;
            }
        }

        [XmlIgnore]
        public string Descriptor
        {
            get
            {
                return _vuelo.Descriptor + " " + _asiento.Descriptor;
            }
        }

        #endregion

        #region Methods

        public void Liberar()
        {
            Estado = EstadoBillete.Disponible;
            _vuelo.Billetes.Remove(this);
        }

        public void Reservar()
        {
            Estado = EstadoBillete.Reservado;
            _vuelo.Billetes.Add(this);
        }

        public string GetXML()
        {
            try
            {
                StringBuilder sb = new StringBuilder("<Billete>");
                sb.AppendFormat("<Codigo>{0}</Codigo>", _codigo);
                sb.AppendFormat("<Vuelo>{0}</Vuelo>", _vuelo.Codigo);
                sb.AppendFormat("<Asiento>{0}</Asiento>", _asiento.Descriptor);
                sb.AppendFormat("<Pasajero>{0}</Pasajero>", this.Pasajero);
                sb.Append("</Billete>");
                return sb.ToString();
            }
            catch (Exception e)
            {
                System.Console.WriteLine(e);
                return null;
            }
        }

        #endregion

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        public override string ToString()
        {
            return Descriptor;
        }

        protected void OnPropertyChanged<T>(Expression<Func<T>> property)
        {
            if (this.PropertyChanged != null)
            {
                var mex = property.Body as MemberExpression;
                string name = mex.Member.Name;
                this.PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }
        #endregion
      
        #region IEquatable<Billete> Members

        public bool Equals(Billete other)
        {
            if (other == null)
                return this == null;

            return other.Codigo == this.Codigo;
        }

        #endregion
    }
}
